package ru.hh.team02.chat.utils;

import java.util.LinkedList;
import java.util.List;

public class SimpleBlockingQueue<T> implements BatchBlockingQueue<T> {

    private final List<T> queue = new LinkedList<T>();
    private volatile boolean terminating = false;

    /*
     * (non-Javadoc)
     * 
     * @see ru.hh.team02.chat.utils.BatchBlockingQueue#get()
     */
    @Override
    public T get() throws InterruptedException {
        synchronized (this) {
            while (queue.isEmpty()) {
                if (terminating) {
                    throw new InterruptedException(
                            "I'm in terminating mode. No more messages.");
                }
                this.wait();
            }
            return queue.remove(0);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * ru.hh.team02.chat.server.SendMessage.sendingBlockingQueue.BlockingQueue
     * #add(T)
     */
    @Override
    public boolean add(T obj) {
        synchronized (this) {
            if (terminating) {
                return false;
            }
            queue.add(obj);
            // notify one thread blocked in the wait section of get method.
            this.notify();
        }
        return true;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * ru.hh.team02.chat.server.SendMessage.sendingBlockingQueue.BlockingQueue
     * #addFront(T)
     */
    @Override
    public boolean addFront(T obj) {
        synchronized (this) {
            if (terminating) {
                return false;
            }
            queue.add(0, obj);
            // notify one thread blocked in the wait section of get method.
            this.notify();
        }
        return true;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * ru.hh.team02.chat.server.SendMessage.sendingBlockingQueue.BlockingQueue
     * #addAll(java.util.List)
     */
    @Override
    public boolean addAll(List<T> objects) {
        synchronized (this) {
            if (terminating) {
                return false;
            }
            queue.addAll(objects);
            // wake up all the waiting threads as there are more then 1 object
            // to process
            this.notifyAll();
        }
        return true;

    }

    /*
     * (non-Javadoc)
     *
     * @see
     * ru.hh.team02.chat.server.SendMessage.sendingBlockingQueue.BlockingQueue
     * #addAllFront(java.util.List)
     */
    @Override
    public boolean addAllFront(List<T> objects) {
        synchronized (this) {
            if (terminating) {
                return false;
            }
            queue.addAll(0, objects);
            // wake up all the waiting threads as there are more then 1 object
            // to process
            this.notifyAll();
        }
        return true;
    }

    /*
     * (non-Javadoc)
     * 
     * @see ru.hh.team02.chat.utils.BatchBlockingQueue#terminate()
     */
    public void terminate() {
        terminating = true;

    }

}
